package com.googlecode.mailnet.netmodel;

import com.googlecode.mailnet.math.distribution.Distribution;

import java.io.Serializable;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * Network node.
 *
 * @author Iskander Akishev
 */
public class Node extends NetworkItem implements Serializable {

	public Set<Link> getIncomingLinks() {
		return incomingLinksView;
	}

	public Set<Link> getOutgoingLinks() {
		return outgoingLinksView;
	}

	public double getFailureProbability() {
		return failureProbability;
	}

	public void setFailureProbability(double failureProbability) {
		checkBeforeModifications();
		this.failureProbability = failureProbability;
	}

	public Distribution getFailureDurationDistribution() {
		return failureDurationDistribution;
	}

	public void setFailureDurationDistribution(Distribution failureDurationDistribution) {
		checkBeforeModifications();
		this.failureDurationDistribution = failureDurationDistribution;
	}

	public void remove() {
		if (!markRemoved()) {
			return;
		}
		
		boolean removed = networkConfiguration.nodes.remove(this);
		assert removed;

		for (Link link : incomingLinks.toArray(new Link[incomingLinks.size()])) {
			link.remove();
		}
		for (Link link : outgoingLinks.toArray(new Link[outgoingLinks.size()])) {
			link.remove();
		}
	}

	// ==================== Implementation ====================
	
	private double failureProbability;
	private Distribution failureDurationDistribution;

	final Set<Link> incomingLinks, outgoingLinks;
	private final Set<Link> incomingLinksView, outgoingLinksView;

	Node(NetworkConfiguration networkConfiguration) {
		super(networkConfiguration);

		this.incomingLinks = new HashSet<Link>();
		this.outgoingLinks = new HashSet<Link>();
		this.incomingLinksView = Collections.unmodifiableSet(incomingLinks);
		this.outgoingLinksView = Collections.unmodifiableSet(outgoingLinks);

		networkConfiguration.nodes.add(this);
	}

	void validate() throws IllegalStateException {
		assert !isRemoved();
		if (failureDurationDistribution == null) {
			throw new IllegalStateException("Failure duration distribution undefined for node \"" + this + "\"");
		}
	}
}
